package test.mdd

import org.goodsl.mdd.annotation.ValueType

import org.goodsl.mdd.Box
import org.junit.Test
import static org.junit.Assert.*
import org.goodsl.mdd.BoxBuilder
import org.codehaus.groovy.runtime.typehandling.GroovyCastException
import org.goodsl.mdd.Seg

/**
 * Created with IntelliJ IDEA.
 * User: Simon Xiao
 * Date: 12-11-2
 * Time: 下午4:19
 * To change this template use File | Settings | File Templates.
 */

class TestParse {

    /**
     * 测试类型解析和初始化
     */
    @Test
    void testParseAndInit(){

        Date d_start1 = new Date("2011/1/13")
        Date d_start2 = new Date("2011/1/14")
        Date d_start3 = new Date("2011/1/15")
        Date d_end = new Date("3012/1/13")   //BoxFirst endDate 构造时会设置为这个值

        BoxFirst b = (BoxFirst)BoxBuilder.makeBox(BoxFirst)

        //验证自动初始化变量值
        assert b.startDate.value !=null
        assert b.startDate.value > d_start1   //自动初始话的值为当前时间

        //验证类型构造函数中已经初始化的变量，不会进行自动初始化
        assert b.endDate.value ==  d_end

        //测试赋值方式1
        b.startDate.value =  d_start1

        //验证直接读取
        assert b.startDate.value ==  d_start1
        //验证数组方式读取.这是groovy语言本身支持的功能
        assert b.startDate["value"] == d_start1
        //验证圆括号方式读取，这方法是动态添加的
        assert b.startDate() == d_start1

        //测试赋值方式2
        b.startDate  d_start2
        assert b.startDate.value ==  d_start2

        //测试赋值方式3
        b.startDate(d_start3)
        assert b.startDate.value ==  d_start3


    }

    @Test
    void testCalcValue(){
        BoxIn1 aBox = (BoxIn1)BoxBuilder.makeBox(BoxIn1)



        assert aBox.f1.enable == false
        assert aBox.f2.enable == true
        assert aBox.num1.age == 50

        //assert aBox.num2.age == 0

        //****测试缺省的类型检查
        try {
            aBox.num1.value = true  //错误！应该输入整数
            fail("未抛出异常")

        }catch (GroovyCastException e){}


        //****测试Box 中依赖属性的类型检查
        try {
            assert aBox.f1.size == true  //错误！aBox.age.size 的计算闭包中故意返回了错误的值
            fail("未抛出异常")

        }catch (GroovyCastException e){}
        //****

        //****测试自定义类型转换器
        aBox.num1.metaClass.castToType = { Object value,Class targetType ->
             if(value.class == Boolean || value.class == boolean ){
                 return 500
             }
        }
        aBox.num1.value = true    //类型不对，上述转换器会给num1.value赋值为500
        aBox.num1.value == 500
        assert aBox.num2.age == 1000
        assert aBox.num2.value == 1500
        //****

        //测试基于依赖关系的级联更新
        aBox.num1.value = 1000
        assert aBox.num2.age == 2000
        assert aBox.num2.value == 3000





    }

    //测试Box嵌套
    @Test
    void testNestBox(){
        BoxFirst box1 = (BoxFirst)BoxBuilder.makeBox(BoxFirst)
        BoxFirst box2 = (BoxFirst)BoxBuilder.makeBox(BoxFirst)

        assert box1.group1.enable == false

        assert box1.group2.enable == true
        box1.width.value = 50
        assert box1.group2.enable == true
        box1.width.value = 200
        assert box1.group2.enable == false


        //group1的enable 只定义了通过width求值，没有定义依赖关系，所以之后计算一次，不会自动更新
        assert box1.group1.enable == false
        box2.width.value = 200
        assert box2.group1.enable == true
    }

    @Test
    void testCompare(){
        BoxFirst box1 = (BoxFirst)BoxBuilder.makeBox(BoxFirst)
        BoxFirst box2 = (BoxFirst)BoxBuilder.makeBox(BoxFirst)

        box1.width.value = 50

        assert box1.width.value == 50

        //这一行语句需要修改了groovy源码才能正常执行
        //assert box1.width == 50

        assert box1.width > 49
        assert box1.width < 51
        assert box1.width >= 50
        assert box1.width <= 50

        box2.width.value = 60

        assert box1.width <= box2.width
    }
    @Test
    void testBoxGetSeg(){
        BoxFirst box1 = (BoxFirst)BoxBuilder.makeBox(BoxFirst)
        Seg seg = box1.getSeg("width")
        assert seg.segInBox.segName == "width"
    }
}

class BoxFirst extends Box {

    BoxIn1 group1
    BoxIn1 group2

    SegDate startDate
    SegDate endDate

    SegInt width

    void init(){
        endDate.value = new Date("3012/1/13")
    }

    @ValueType(boolean)
    def dep_visible = {
        group1{
            startDate{it.visible}
        }
        startDate{
            it.value > new Date()
        }
    }
    @ValueType(boolean)
    def dep_enable = {
        group1{
            width.value > 100
        }
        group2{
            width{
                it.value<100
            }
        }
    }

}

class BoxIn1 extends Box{
    SegInt f1
    SegInt f2

    SegInt num1
    SegInt num2
    SegInt num3


    def dep_value = {
       num2{
           num1{it.value * 3}
       }
    }

    @ValueType(boolean)
    def dep_enable ={

        f2{
            !(f1{
                false
            })
        }
        f1{false}
    }
    @ValueType(int)
    def dep_size = {
        f1{
            "hello"
        }
    }
    @ValueType(int)
    def dep_halue = {
        f2{
            f1{ it.value }
        }
    }
    @ValueType(int)
    def dep_age={
        num1{
            50
        }
        num2{
            num1{
                it.value
            } * 2}
    }
}

@ValueType(int)
class SegInt extends Seg {

}
@ValueType(Date)
class SegDate extends Seg  {

}